#include"include/allinall_shader.hpp"

//------------------------------
//glsl

//print the glsl source

void glsl::listglsl(const char type){
	switch(type){
		case 'a':
		case 'v':
		printf("-------- vertex source\n");
		for(int i=0;i<vtx.size();++i)
			printf("%d:%s\n",i,vtx[i].name);
		if(type=='v')
			break;
		case 'f':
		printf("------ fragment source\n");
		for(int i=0;i<frg.size();++i)
			printf("%d:%s\n",i,frg[i].name);
		break;
		default:
		printf("you can choose:\n\ta:all\n\tv:vertex shader\n\tf:fragment shader\n");
	}
}
//add glsl
void glsl::addglsl(const char*glslfile,const unsigned short glsltype){
	if((glsltype!=GL_VERTEX_SHADER)&&(glsltype!=GL_FRAGMENT_SHADER)){
		printf("Unknown glsl_type\n");
		return;
	}
	if(glsltype==GL_VERTEX_SHADER)
		for(int i=0;i<vtx.size();++i)
			if(!strcmp(vtx[i].name,glslfile)){
				printf("already have %s(%d)\n",glslfile,i);
				return;
			}
	if(glsltype==GL_FRAGMENT_SHADER)
		for(int i=0;i<frg.size();++i)
			if(!strcmp(frg[i].name,glslfile)){
				printf("already have %s(%d)\n",glslfile,i);
				return;
			}
	FILE*codefile=fopen(glslfile,"r");
	if(!codefile){
		perror("Fail code_open\n");
		return;
	}
	char code[100000];
	code[fread(code,sizeof(char),100000,codefile)]='\0';
	if(ferror(codefile)){
		perror("Fail code_read\n");
		fclose(codefile);
		return;
	}
	fclose(codefile);
	// printf("vtx:%d\tfrg:%d\n",GL_VERTEX_SHADER,GL_FRAGMENT_SHADER);
	// printf("%d\n",glsltype);
	unsigned int ID=glCreateShader(glsltype);
	const char*constcode=code;
	glShaderSource(ID,1,&constcode,NULL);
	glCompileShader(ID);
	int temp=0;
	glGetShaderiv(ID,GL_COMPILE_STATUS,&temp);
	if(temp==GL_FALSE){
		printf("Fail glsl_compile\n");
		return;
	}
	if(glsltype==GL_VERTEX_SHADER){
		vtx.push_back(source_with_name{glslfile,ID});
		// printf("<><%d\n",ID);
	}
	else{
		frg.push_back(source_with_name{glslfile,ID});
		// printf("<>|<%d\n",ID);
	}
}

glsl::~glsl(){
	for(int i=0;i<vtx.size();++i)
		glDeleteShader(vtx[i].ID);
	for(int i=0;i<frg.size();++i)
		glDeleteShader(frg[i].ID);
}

//------------------------------
//shader

void shader::chgcontext(size_t v,size_t f){
	// printf("%d:%d\n",source->vtx[v].ID,source->frg[f].ID);
	glAttachShader(SID,source->vtx[v].ID);
	glAttachShader(SID,source->frg[f].ID);
	strncpy(glsltake[0],source->vtx[v].name,strlen(source->vtx[v].name)+1);
	strncpy(glsltake[1],source->frg[f].name,strlen(source->frg[f].name)+1);
	glLinkProgram(SID);

		// int success = 0;
		// char infoLog[512];
		// glGetProgramiv(SID, GL_LINK_STATUS, &success);
		// if (!success)
		// {
		// 	glGetProgramInfoLog(SID, 512, NULL, infoLog);
		// 	printf("ERROR::PROGRAM::LINK::FAIL\n%s\n",infoLog);
		// }
}
shader::shader(glsl&from,int v=-1,int f=-1){
	SID=glCreateProgram();
	source=&from;
	if(v>-1&&f>-1)
		chgcontext(v,f);
}
shader::~shader(){
	glDeleteProgram(SID);
}
void shader::use(){
	glUseProgram(SID);
}